package org.whatever.aha.zjut.platform.service;

import cn.dev33.satoken.stp.StpUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.Caching;
import org.springframework.context.annotation.Lazy;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestBody;
import org.whatever.aha.zjut.base.constant.ErrorCode;
import org.whatever.aha.zjut.base.constant.StatusConstant;
import org.whatever.aha.zjut.base.exception.AppException;
import org.whatever.aha.zjut.base.exception.app.AccountBlockedException;
import org.whatever.aha.zjut.platform.dto.AcademyRegisterInfo;
import org.whatever.aha.zjut.platform.entity.AcademyAdmin;
import org.whatever.aha.zjut.platform.entity.StudentInfo;
import org.whatever.aha.zjut.platform.entity.User;
import org.whatever.aha.zjut.platform.mapper.StudentInfoMapper;
import org.whatever.aha.zjut.platform.mapper.UserMapper;
import org.whatever.aha.zjut.platform.vo.AcademyInfoVo;
import org.whatever.aha.zjut.platform.vo.UserRoughInfoVo;

import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * @author Baby_mo
 */
@Service
@RequiredArgsConstructor
@CacheConfig(cacheNames = "ExpireOneMin")
public class UserService {
    final UserRoleService userRoleService;
    final UserMapper userMapper;
    final PasswordEncoder passwordEncoder;
    final StudentInfoMapper studentInfoMapper;

    @Autowired
    @Lazy
    private AcademyAdminService academyAdminService;

    /**
     * 通过ID查询用户
     */
    @Cacheable(key = "'user_'+#userId")
    public User getUserById(Integer userId) {
        return userMapper.selectOne(new QueryWrapper<User>().eq("user_id", userId));
    }

    /**
     * 通过手机号或用户名查询用户
     */
    @Cacheable(key = "'user_'+#username")
    public User getUserByUsernameOrPhone(String username) {
        return userMapper.selectOne(new QueryWrapper<User>().eq("username", username).or().eq("phone_number", username));
    }

    /**
     * 通过手机号查询用户是否存在
     */
    @Cacheable(key = "'not_exist_'+#phoneNumber")
    public boolean exist(String phoneNumber) {
        int count = userMapper.selectCount(new QueryWrapper<User>().eq("phone_number", phoneNumber));
        return count != 0;
    }

    /**
     * 检查账户是否过期
     */
    public void checkAccount(User user) {
        if (user.getDisabled()){
            throw new AccountBlockedException(Map.of("username", user.getUsername(), "untie_time", user.getUntieTime()));
        }
    }

    /**
     * 更新密码
     */
    @Transactional(rollbackFor = Exception.class)
    @Caching(evict = {
            @CacheEvict(key = "'user_'+#user.userId"),
            @CacheEvict(key = "'user'+#user.username"),
            @CacheEvict(key = "'user'+#user.phoneNumber")}
    )
    public void resetPassword(User user, String password) {
        user.setPassword(passwordEncoder.encode(password));
        userMapper.updateById(user);
    }

    /**
     * 获取当前登陆用户
     */
    public User getLoginUser() {
        int userId = StpUtil.getLoginIdAsInt();
        return getUserById(userId);
    }

    /**
     * 获取当前用户登陆类型
     */
    public int getLoginType(int userId) {
        return userMapper.getLoginTypeById(userId);
    }


    /**
     * 根据userId获取学生粗略信息（实名）
     *
     * @param userId
     * @return
     */
    public UserRoughInfoVo getStuRoughInfoById(int userId){
        StudentInfo studentInfo = studentInfoMapper.selectById(userId);
        if(studentInfo == null){
            throw new AppException(ErrorCode.STUDENT_INFO_LACK);
        }
        return new UserRoughInfoVo(userId, studentInfo.getRealName());
    }

    /**
     * 根据userId获取用户粗略信息（用户名）
     *
     * @param userId
     * @return
     */
    public UserRoughInfoVo getUserRoughInfoById(int userId){
        User user = userMapper.selectById(userId);
        if(user == null){
            throw new AppException(ErrorCode.USER_NOT_EXIST);
        }
        return new UserRoughInfoVo(userId, user.getUsername());
    }


    /**
     * 校级管理员新建院级管理员账号
     *
     * @param academyRegisterInfo
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public int createAcademy(AcademyRegisterInfo academyRegisterInfo){
        //在用户表中增加信息
        User user = User.build(StatusConstant.IDENTITY_ACADEMY_ADMIN.getCode());
        BeanUtils.copyProperties(academyRegisterInfo, user);
        user.setPassword(passwordEncoder.encode(academyRegisterInfo.getPassword()));
        userMapper.insert(user);
        //在用户-角色表中增加信息
        userRoleService.addUserRole(user.getUserId(), StatusConstant.IDENTITY_ACADEMY_ADMIN.getCode());
        //在学院管理员-学院信息表中加入信息
        return academyAdminService.addAcademyAdmin(user.getUserId(), academyRegisterInfo.getAcademyId());

    }

    /**
     * 校级管理员删除院级管理员账号
     *
     * @param userId
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public int deleteAcademy(int userId){
        academyAdminService.deleteAcademyAdmin(userId);
        userRoleService.deleteOneUR(userId, StatusConstant.IDENTITY_ACADEMY_ADMIN.getCode());
        return userMapper.deleteById(userId);
    }

    /**
     * 分页获取院级管理员信息
     *
     * @param academyIdList
     * @param offset
     * @param pageSize
     * @return
     */
    public Map getAcademyAccountPageable(List<Integer> academyIdList, int offset, int pageSize) {
        List<AcademyInfoVo> academyAccountPageable = userMapper.getAcademyAccountPageable(academyIdList, offset, pageSize);
        int total = userMapper.getAcademyAccountTotal(academyIdList);
        return Map.of("data", academyAccountPageable, "total", total);

    }

    /**
     * 修改院级管理员信息
     *
     * @param userId
     * @param username
     * @param password
     * @param phoneNumber
     * @param academyId
     * @param disable
     * @param untie_time
     * @return
     */
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public int modifyAcademyAccount(int userId, String username, String password, String phoneNumber, Integer academyId, Boolean disable, Date untie_time){
        User user = userMapper.selectById(userId);
        if(username != null && username.length() > 0){user.setUsername(username);}
        if(password != null && password.length() > 0){user.setPassword(passwordEncoder.encode(password));}
        if(phoneNumber != null && phoneNumber.length() > 0){user.setPhoneNumber(phoneNumber);}
        if(disable != null){user.setDisabled(disable);}
        if(untie_time != null){user.setUntieTime(untie_time);}
        if(academyId != null){academyAdminService.updateAcademyAdmin(userId, academyId);}
        return userMapper.updateById(user);
    }

    /**
     * 获取所有用户的手机号
     *
     * @return
     */
    public List<Object> getAllPhones(){
        return userMapper.selectObjs(new QueryWrapper<User>().select("phone_number"));
    }

    /**
     * 获取所有评委的用户名
     *
     * @return
     */
    public List<Object> getAllJudgeNames(){
        return userMapper.selectObjs(new QueryWrapper<User>().eq("login_type", StatusConstant.IDENTITY_JUDGE.getCode()).select("username"));
    }

    /**
     * 校级管理员新建评委账号
     *
     * @param password
     * @param userName
     * @param ddl
     * @param phone
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public int createJudge(String password, String userName, Date ddl, String phone){
        //在用户表中增加信息
        User user = User.build(StatusConstant.IDENTITY_JUDGE.getCode());
        user.setUsername(userName);
        user.setPhoneNumber(phone);
        user.setUntieTime(ddl);
        user.setPassword(passwordEncoder.encode(password));
        userMapper.insert(user);
        //在用户-角色表中增加信息
        userRoleService.addUserRole(user.getUserId(), StatusConstant.IDENTITY_JUDGE.getCode());
        //返回userId
        return user.getUserId();
    }

    /**
     * 修改评委信息
     *
     * @param password
     * @param userName
     * @param ddl
     * @param phone
     * @return
     */
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public int modifyJudgeAccount(int userId, String password, String userName, Date ddl, String phone){
        User user = userMapper.selectById(userId);
        if(userName != null && userName.length() > 0){user.setUsername(userName);}
        if(password != null && password.length() > 0){user.setPassword(passwordEncoder.encode(password));}
        if(phone != null && phone.length() > 0){user.setPhoneNumber(phone);}
        if(ddl != null){user.setUntieTime(ddl);}
        return userMapper.updateById(user);
    }

    /**
     * 校级管理员删除评委账号
     *
     * @param userId
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public int deleteJudgeAccount(int userId){
        userRoleService.deleteOneUR(userId, StatusConstant.IDENTITY_JUDGE.getCode());
        return userMapper.deleteById(userId);
    }



}
